home *** CD-ROM | disk | FTP | other *** search
- /* $Id: plfill.c,v 1.14 1994/06/30 18:22:07 mjl Exp $
- * $Log: plfill.c,v $
- * Revision 1.14 1994/06/30 18:22:07 mjl
- * All core source files: made another pass to eliminate warnings when using
- * gcc -Wall. Lots of cleaning up: got rid of includes of math.h or string.h
- * (now included by plplot.h), and other minor changes. Now each file has
- * global access to the plstream pointer via extern; many accessor functions
- * eliminated as a result.
- *
- * Revision 1.13 1994/04/30 16:15:11 mjl
- * Fixed format field (%ld instead of %d) or introduced casts where
- * appropriate to eliminate warnings given by gcc -Wall.
- *
- * Revision 1.12 1994/03/23 08:12:54 mjl
- * Split into two routines, one as a front-end to the driver interface fill
- * routine, and the other as a target of the driver interface when the driver
- * doesn't support the desired fill capability.
- */
-
- /* plfill.c
-
- Polygon pattern fill.
- */
-
- #include "plplotP.h"
-
- #define DTOR 0.0174533
- #define BINC 50
-
- struct point {
- PLINT x, y;
- };
- static PLINT bufferleng, buffersize, *buffer;
-
- /* Static function prototypes */
- /* INDENT OFF */
-
- static int compar (const void *, const void *);
- static void addcoord (PLINT, PLINT);
- static void tran (PLINT *, PLINT *, PLFLT, PLFLT);
- static void buildlist (PLINT, PLINT, PLINT, PLINT, PLINT, PLINT, PLINT);
-
- /* INDENT ON */
-
- /*----------------------------------------------------------------------*\
- * void plfill()
- *
- * Pattern fills the polygon bounded by the input points.
- * If hardware fill is used, a maximum of PL_MAXPOLY-1 vertices is allowed.
- * The final point is explicitly added if it doesn't match up to the first,
- * to prevent clipping problems.
- \*----------------------------------------------------------------------*/
-
- void
- c_plfill(PLINT n, PLFLT *x, PLFLT *y)
- {
- short xpoly[PL_MAXPOLY], ypoly[PL_MAXPOLY];
- PLINT i;
-
- if (plsc->level < 3) {
- plabort("plfill: Please set up window first");
- return;
- }
- if (n < 3) {
- plabort("plfill: Not enough points in object");
- return;
- }
- if (n > PL_MAXPOLY-1) {
- plwarn("plfill: too many points in polygon");
- n = PL_MAXPOLY;
- }
- for (i = 0; i < n; i++) {
- xpoly[i] = plP_wcpcx(x[i]);
- ypoly[i] = plP_wcpcy(y[i]);
- }
-
- if (x[0] != x[n-1] || y[0] != y[n-1]) {
- n++;
- xpoly[n-1] = plP_wcpcx(x[0]);
- ypoly[n-1] = plP_wcpcy(y[0]);
- }
-
- plP_fill(xpoly, ypoly, n);
- }
-
- /*----------------------------------------------------------------------*\
- * void plfill_soft()
- *
- * Pattern fills in software the polygon bounded by the input points.
- \*----------------------------------------------------------------------*/
-
- void
- plfill_soft(short *x, short *y, PLINT n)
- {
- PLINT i, j;
- PLINT xp1, yp1, xp2, yp2, xp3, yp3;
- PLINT k, dinc;
- PLFLT ci, si;
- double temp;
-
- buffersize = 2 * BINC;
- buffer = (PLINT *) malloc((size_t) buffersize * sizeof(PLINT));
- if ( ! buffer) {
- plabort("plfill: Out of memory");
- return;
- }
-
- /* Loop over sets of lines in pattern */
-
- for (k = 0; k < plsc->nps; k++) {
- bufferleng = 0;
-
- temp = DTOR * plsc->inclin[k] * 0.1;
- si = sin(temp) * plsc->ypmm;
- ci = cos(temp) * plsc->xpmm;
-
- /* normalize: 1 = si*si + ci*ci */
-
- temp = sqrt((double) (si*si + ci*ci));
- si /= temp;
- ci /= temp;
-
- dinc = plsc->delta[k] * SSQR(plsc->ypmm * ABS(ci),
- plsc->xpmm * ABS(si)) / 1000.;
-
- if (dinc < 0) dinc = -dinc;
- if (dinc == 0) dinc = 1;
-
- xp1 = x[n-2];
- yp1 = y[n-2];
- tran(&xp1, &yp1, (PLFLT) ci, (PLFLT) si);
-
- xp2 = x[n-1];
- yp2 = y[n-1];
- tran(&xp2, &yp2, (PLFLT) ci, (PLFLT) si);
-
- /* Loop over points in polygon */
-
- for (i = 0; i < n; i++) {
- xp3 = x[i];
- yp3 = y[i];
- tran(&xp3, &yp3, (PLFLT) ci, (PLFLT) si);
- buildlist(xp1, yp1, xp2, yp2, xp3, yp3, dinc);
- xp1 = xp2;
- yp1 = yp2;
- xp2 = xp3;
- yp2 = yp3;
- }
-
- /* Sort list by y then x */
-
- qsort((void *) buffer, (size_t) bufferleng / 2,
- (size_t) sizeof(struct point), compar);
-
- /* OK, now do the hatching */
-
- i = 0;
-
- while (i < bufferleng) {
- xp1 = buffer[i];
- yp1 = buffer[i + 1];
- i += 2;
- xp2 = xp1;
- yp2 = yp1;
- tran(&xp1, &yp1, (PLFLT) ci, (PLFLT) (-si));
- plP_movphy(xp1, yp1);
- xp1 = buffer[i];
- yp1 = buffer[i + 1];
- i += 2;
- if (yp2 != yp1) {
- fprintf(stderr, "plfill: oh oh we are lost\n");
- for (j = 0; j < bufferleng; j+=2) {
- fprintf(stderr, "plfill: %d %d\n",
- (int) buffer[j], (int) buffer[j+1]);
- }
- continue; /* Uh oh we're lost */
- }
- tran(&xp1, &yp1, (PLFLT) ci, (PLFLT) (-si));
- plP_draphy(xp1, yp1);
- }
- }
- free((void *) buffer);
- }
-
- /*----------------------------------------------------------------------*\
- * Utility functions
- \*----------------------------------------------------------------------*/
-
- static void
- tran(PLINT *a, PLINT *b, PLFLT c, PLFLT d)
- {
- PLINT ta, tb;
-
- ta = *a;
- tb = *b;
-
- *a = floor((double) (ta * c + tb * d + 0.5));
- *b = floor((double) (tb * c - ta * d + 0.5));
- }
-
- static void
- buildlist(PLINT xp1, PLINT yp1, PLINT xp2, PLINT yp2, PLINT xp3, PLINT yp3,
- PLINT dinc)
- {
- PLINT min_y, max_y;
- PLINT dx, dy, cstep, nstep, ploty, plotx;
-
- dx = xp2 - xp1;
- dy = yp2 - yp1;
-
- if (dy == 0) {
- if (yp2 > yp3 && ((yp2 % dinc) == 0))
- addcoord(xp2, yp2);
- return;
- }
-
- if (dy > 0) {
- cstep = 1;
- min_y = yp1;
- max_y = yp2;
- }
- else {
- cstep = -1;
- min_y = yp2;
- max_y = yp1;
- }
-
- nstep = (yp3 > yp2 ? 1 : -1);
- if (yp3 == yp2) nstep = 0;
-
- /* Build coordinate list */
-
- ploty = (min_y / dinc) * dinc;
- if (ploty < min_y) ploty += dinc;
-
- for (; ploty <= max_y; ploty += dinc) {
- if (ploty == yp1) continue;
- if (ploty == yp2) {
- if (cstep == -nstep) continue;
- if (yp2 == yp3 && yp1 > yp2) continue;
- }
- plotx = xp1 + floor(((double) (ploty - yp1) * dx) / dy + 0.5);
- addcoord(plotx, ploty);
- }
- }
-
- static void
- addcoord(PLINT xp1, PLINT yp1)
- {
- PLINT *temp;
-
- if (bufferleng + 2 > buffersize) {
- buffersize += 2 * BINC;
- temp = (PLINT *) realloc((void *) buffer,
- (size_t) buffersize * sizeof(PLINT));
- if (!temp) {
- free((void *) buffer);
- plexit("plfill: Out of memory!");
- }
- buffer = temp;
- }
-
- buffer[bufferleng++] = xp1;
- buffer[bufferleng++] = yp1;
- }
-
- static int
- compar(const void *pnum1, const void *pnum2)
- {
- const struct point *pnt1, *pnt2;
-
- pnt1 = (const struct point *) pnum1;
- pnt2 = (const struct point *) pnum2;
-
- if (pnt1->y < pnt2->y)
- return -1;
- else if (pnt1->y > pnt2->y)
- return 1;
-
- /* Only reach here if y coords are equal, so sort by x */
-
- if (pnt1->x < pnt2->x)
- return -1;
- else if (pnt1->x > pnt2->x)
- return 1;
-
- return 0;
- }
-